home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 151-175 / disk_175 / virusx / virusx.c < prev    next >
Text File  |  1992-05-06  |  55KB  |  1,653 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*                                                                      */
  4. /*                                VirusX                                */
  5. /*                                                                      */
  6. /*                           by Steve Tibbett                           */
  7. /*                                                                      */
  8. /*                                                                      */
  9. /*              Please - if you find a new virus, Send me a copy!       */
  10. /*              (And warn me it's on the disk!).  I want to keep        */
  11. /*              this program current.  (Feel free to put something      */
  12. /*              neat on the disk also!)                                 */
  13. /*                                                                      */
  14. /*  This version of VirusX is my first done with the Lattice 5.0        */
  15. /*  compiler.  The Lattice compiler, with the help of John Toebes,      */
  16. /*  gave me an executable almost 4K smaller than the best I could       */
  17. /*  get out of Manx.  Reason enough for me to switch!                   */
  18. /*                                                                      */
  19. /*  The Makefile included in the "source.zoo" file you should have      */
  20. /*  gotten in the VirusX.Zoo file this came from, is set up for the     */
  21. /*  MANX Make Utility.  Switching to Lattice's LMK should be easy,      */
  22. /*  but I've had no reason to.  The important thing is the command      */
  23. /*  line switches and the BLINK command line.                           */
  24. /*                                                                      */
  25. /*  Thanks to John Toebes for a lot of help getting it going, and       */
  26. /*  thanks to Dan James for providing the routine down at the bottom    */
  27. /*  that actually takes the IRQ Virus out of executable files.          */
  28. /*                                                                      */
  29. /************************************************************************/
  30. /*                                                                      */
  31. /*  History:                                                            */
  32. /*  --------                                                            */
  33. /*      April '88 or so:  V1.0 written and released.                    */
  34. /*     A few days later:  V1.01 released.  V1.0 wrote garbage to the    */
  35. /*                        disk if it was write protected then fixed.    */
  36. /*          27-March-88:  V1.2 released.  V1.2's purpose in life was    */
  37. /*                        to deal with the Byte Bandit virus.           */
  38. /*                        (Actually, it's well after midnight - make    */
  39. /*                        that March 28th. :)                           */
  40. /*          28-March-88:  Oops, V1.2 was 3K or so bigger than it needed */
  41. /*                        to be.  Fix it, release v1.21.                */
  42. /*           15-June-88:  V1.3, V1.2 cleaned up and made smaller.       */
  43. /*            8-July-88:  V1.4.  Revenge virus checking, Viewbooting,   */
  44. /*                        check for SCA in RAM, more cleaning up.       */
  45. /*           24-July-88:  V1.5, only change was the addition of the     */
  46. /*                        Byte Warrior virus.                           */
  47. /*             1-Aug-88:  V1.6 (busy week), Dan Mosedale sent me the    */
  48. /*                        Northstar Virus.  Nuked it.                   */
  49. /*            18-Aug-88:  V1.7 - after 2 weeks off, got the Obelisk     */
  50. /*                        Softworks crew virus.                         */
  51. /*     a few days later:  V1.71, can't remember why.                    */
  52. /*   September Sometime:  Biggest mistake of my life, released V2.0.    */
  53. /*         3 days later:  Bigger mistake:  Released V2.01 - which was   */
  54. /*                        2.0 with another bug added.  Argh.            */
  55. /*             6-Nov-88:  Finally got some time to clean things up,     */
  56. /*                        check out the startup code bugs, clean up the */
  57. /*                        docs and source, and release V2.1.  There     */
  58. /*                        haven't been any new viruses in about a month */
  59. /*                        now, but I hear one or two are on the way.    */
  60. /*            31-Dec-88:  Got the IRQ virus yesterday.  Neat one!       */
  61. /*                        Releasing V3.0 tonite or tomorrow to handle   */
  62. /*                        it.  See description below.                   */
  63. /*            04-Jan-89:  Got 2 new viruses, released 3.1.              */
  64. /*                                                                      */
  65. /************************************************************************/
  66. /*                                                                      */
  67. /*  Viruses Dealt With:                                                 */
  68. /*  -------------------                                                 */
  69. /*                                                                      */
  70. /*      SCA             - The SCA is the simplest virus to deal with,   */
  71. /*                        as it's not actually DOING anything except    */
  72. /*                        hiding in memory, until you reboot.           */
  73. /*                        We just look at CoolCapture and fix it to get */
  74. /*                        it out of RAM.                                */
  75. /*                                                                      */
  76. /*      Byte Bandit     - The Byte Bandit virus takes the DoIO() vector */
  77. /*                        and redirects it through itself.  Thus, any   */
  78. /*                        attempt to read or write the boot block (ie,  */
  79. /*                        AmigaDOS trying to figure out what kind of    */
  80. /*                        disk it is) results in the BB writing itself  */
  81. /*                        onto that disk.  VirusX couldn't just rewrite */
  82. /*                        the boot block, we have to get him out of RAM */
  83. /*                        first.  This virus also has an interrupt that */
  84. /*                        crashes the machine every 5 minutes or so     */
  85. /*                        after it's infected a few of your disks.  Ow. */
  86. /*                        It stays in memory not via the Capture        */
  87. /*                        vectors, but by a Resident module.            */
  88. /*                                                                      */
  89. /*      Revenge         - Basically, a Byte Bandit clone except it will */
  90. /*                        bring up an obscene pointer a few minutes     */
  91. /*                        after you reboot.  We treat it much like the  */
  92. /*                        byte bandit.                                  */
  93. /*                                                                      */
  94. /*      Byte Warrior    - Jumps right into 1.2 Kickstart.  Won't work   */
  95. /*                        under 1.3.  Hangs around via Resident struct, */
  96. /*                        doesn't do any damage.                        */
  97. /*                                                                      */
  98. /*      North Star      - Like SCA, hangs around via CoolCapture,       */
  99. /*                        killing CoolCapture kills the North Star.     */
  100. /*                                                                      */
  101. /*      Obelisk Softworks Crew                                          */
  102. /*                      - Hangs around via CoolCapture, also            */
  103. /*                        watches reads of DoIO() (but doesn't          */
  104. /*                        infect EVERY disk - onlyt ones you boot       */
  105. /*                        off of)                                       */
  106. /*                                                                      */
  107. /*       IRQ            - This is the FIRST Non-Bootblock Virus.        */
  108. /*                        It copies itself from place to place via the  */
  109. /*                        first executable program found in your        */
  110. /*                        startup-sequence.  It SetFunction's           */
  111. /*                        OldOpenLibrary(), has a KickTagPtr,           */
  112. /*                        and lives in the first hunk of an             */
  113. /*                        infected program.                             */
  114. /*                        THANKS! to Gary Duncan and Henrik Clausen for */
  115. /*                        being the first to send this one to me!       */
  116. /*                                                                      */
  117. /*  Pentagon Circle     - This one looks at the DoIO vector, and has    */
  118. /*                        a CoolCapture vector.  It will write itself   */
  119. /*                        over any virus inserted, but not onto         */
  120. /*                        anything else.  (Neat idea!).  No danger,     */
  121. /*                        easy to eliminate.  Holding left button       */
  122. /*                        while booting with this one shows different   */
  123. /*                        screen colour, but doesn't get rid of it.     */
  124. /*                        Thanks to Bill at CMI (CMI*BILL on Plink)     */
  125. /*                        for sending me this one!                      */
  126. /*                                                                      */
  127. /*  SystemZ Virus Protector                                             */
  128. /*                      - This is another 'virus protector' that        */
  129. /*                        can write itself to disks.  Anything that     */
  130. /*                        spreads itself, under any name, is a          */
  131. /*                        virus.  Doesn't do anything except during     */
  132. /*                        a reboot, then examines disks and writes      */
  133. /*                        over viruses.  Again, from CMI*BILL.          */
  134. /*                                                                      */
  135. /*  Thanks also to Robb Walton for being the first to send one of the   */
  136. /*  other ones, (but I can't remember which one anymore... 8-(  )       */
  137. /************************************************************************/
  138. /*                                                                      */
  139. /*  Notes on making VirusX yourself:  The source is included mainly     */
  140. /*  for your perusal, not so that you can modify it and redistribute    */
  141. /*  it.  I've modified Manx's _main.c module to make the detach         */
  142. /*  from the initial CLI work properly.  I can't redistribute this      */
  143. /*  module since it's copyright manx, so here's VirusX without it.      */
  144. /*  It will compile and run, but if you run it from WB, it won't quit.  */
  145. /*  The version I've supplied should do everything just fine.           */
  146. /*                                                                      */
  147. /************************************************************************/
  148.  
  149.  
  150. #include <stdio.h>
  151. #include <ctype.h>
  152. #include <stdlib.h>
  153. #include <exec/types.h>
  154. #include <intuition/intuition.h>
  155. #include <devices/bootblock.h>
  156. #include <devices/trackdisk.h>
  157. #include <exec/execbase.h>
  158. #include <exec/memory.h>
  159. #include <libraries/dos.h>
  160. #include <libraries/dosextens.h>
  161. #include <pragmas/all.h>
  162. #include <proto/all.h>
  163. #include <String.h>
  164. #include "virusx.i"
  165.  
  166.  
  167. /* Latticeisms */
  168. void MemCleanup() {}
  169.  
  170.  
  171. /********************************************************************/
  172. /* These string constants are used in multiple places, and thus     */
  173. /* save bytes by having only one copy of them.                      */
  174. /********************************************************************/
  175. char TITLETEXT[]        = "VirusX 3.10 by Steve Tibbett";
  176. char TDName[]           = "trackdisk.device";
  177. char copystring[]       = "(Copy Count on this disk: %d)";
  178. char ITBodyText[80];
  179. char VN_OBELISK[]       = "Obelisk";
  180. char VN_NORTHSTAR[]     = "North Star";
  181. char VN_SCA[]           = "SCA";
  182. char VN_BYTEBANDIT[]    = "Byte Bandit";
  183. char VN_BYTEWARRIOR[]   = "Byte Warrior";
  184. char VN_REVENGE[]       = "Revenge";
  185. char VN_IRQ[]           = "IRQ";
  186. char VN_PENTAGON[]      = "Pentagon Circle";
  187. char VN_SYSTEMZ[]    = "SystemZ";
  188. char CaptureStr[]       = "Capture is pointing at $";
  189. char text[]             = "DF6: Boot Sectors";
  190.  
  191. #define WIN_SIZE     122L
  192.  
  193. /* Release Date of this version of VirusX */
  194. char date[]             = "January 4, 1988";
  195.  
  196.  
  197. /********************************************************************/
  198. /* These counters are for the Info window, one for each virus.      */
  199. /********************************************************************/
  200. int     ObeliskCount;
  201. int     NorthStarCount;
  202. int     SCACount;
  203. int     ByteBanditCount;
  204. int     ByteWarriorCount;
  205. int     RevengeCount;
  206. int     IRQFound;
  207. int    PentagonCount;
  208. int    SystemZCount;
  209.  
  210.  
  211. /*******************************************************************/
  212. /*  Miscellaneous variables.                                       */
  213. /*******************************************************************/
  214. long    ChangeCount[4];                 /* TD_CHANGECOUNT for 4 drives  */
  215. long    LastSum;                        /* Used in the checksumming     */
  216. long    error;                          /* sort of a temporary variable */
  217. char    WindowBig;                      /* TRUE if the window is big    */
  218. struct  Port *diskport;                 /* trackdisk's port.            */
  219. struct  IOStdReq *diskreq;              /* trackdisk's IOStdReq         */
  220. int     DisksChecked, DisksInstalled;   /* for title bar info           */
  221. long    VirusBase;                      /* ick, whatta name!            */
  222. char    FromCLI;                        /* True if run from CLI         */
  223. struct Process *Process;
  224.  
  225. struct IntuitionBase    *IntuitionBase; /* For Library Bindings         */
  226. struct GfxBase          *GfxBase;
  227. struct Window           *Window;
  228. struct IntuiMessage     *Message;
  229. struct ExecBase         *ExecBase;
  230.  
  231. struct IOStdReq         *TimerReq;
  232. struct MsgPort          *TimerPort;
  233.  
  234. static long fp;
  235.  
  236. char Keepgoing;         /* A flag.  It's false when we want out.        */
  237. long x, y, i;           /* Left over from my using Basic                */
  238. char flag;              /* Another flag.  Lets start our own country.   */
  239. LONG thing1, thing2;
  240.  
  241. struct NewWindow NewWindow =
  242.         {
  243.         128,0,  309,10,  0,1,
  244.         DISKINSERTED | CLOSEWINDOW | VANILLAKEY | NEWSIZE | MOUSEBUTTONS,       /* IDCMP Flagz */
  245.         WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
  246.         NULL, NULL,TITLETEXT,
  247.         NULL,NULL,0,0,0,0,WBENCHSCREEN,
  248.         };
  249.  
  250. struct RastPort *RP;
  251.  
  252. #define BSIZE 40        /* Ha!  I'm not telling what this is! */
  253.  
  254.  
  255. /*******************************************************************/
  256. /*  diskbuffer is where all disk io goes to.  it's 3*512 rather    */
  257. /*  than 2*512, because I believe one of the viruses watches for   */
  258. /*  reads of 1024 bytes, so I'm just being safe.                   */
  259. /*******************************************************************/
  260. UBYTE *diskbuffer;
  261.  
  262.  
  263. /************************************************************************/
  264. /* Warning messages.  These messages get modified before being          */
  265. /* displayed (Unless you DO have a DF9:)                                */
  266. /************************************************************************/
  267. char TEXTPTR[] = "Danger:  The disk in DF9: is";
  268. char NBCTEXT[] = "Danger:  The disk in DF9: has";  /* What a waste, eh? */
  269. char CopyText[40];
  270.  
  271. /*************************************************************************/
  272. /*   This is a byte by byte copy of working boot block code.  Check it   */
  273. /*   out if you like.  This is what gets written back to the disk when   */
  274. /*   you ask VirusX to fix a disk.                                       */
  275. /*************************************************************************/
  276. unsigned char bootblock[] = { 'D', 'O', 'S', 0,
  277. 0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
  278. 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
  279. 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
  280. 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  281. 0x00, 0x00};
  282.  
  283.  
  284. /********************************************************************/
  285. /*  My intuition defines.  There's lots of 'em - theyre self explan.*/
  286. /********************************************************************/
  287.  
  288. struct TextAttr TxtAt_Plain =
  289.         {
  290.         "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
  291.         };
  292.  
  293. /***  Non SCA warning requester IntuiText's ***/
  294.  
  295. struct IntuiText Body2 =
  296.         {
  297.         0, 1,  JAM2, 20,18, &TxtAt_Plain, "Nonstandard Boot Code!", NULL
  298.         };
  299.  
  300. struct IntuiText Body1 =
  301.         {
  302.         0,1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2
  303.         };
  304.  
  305. /*-  This one says "The disk in DFx: is"  -*/
  306.  
  307. struct IntuiText GenericFirstBody =
  308.         {
  309.         0,1, JAM2, 20,8,&TxtAt_Plain, (UBYTE *)TEXTPTR, 0
  310.         };
  311.  
  312.  
  313. /***** Generic IntuiTexts used as of V1.7 ******/
  314.  
  315. struct IntuiText GenericDiskBody =
  316.         {
  317.         0,1, JAM2, 20,18, &TxtAt_Plain,ITBodyText, &GenericFirstBody
  318.         };
  319.  
  320. struct IntuiText SCAPos =
  321.         {
  322.         0,1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL
  323.         };
  324.  
  325. struct IntuiText Repair =
  326.         {
  327.         0,1, JAM2, 7,3, &TxtAt_Plain, "Repair it", NULL
  328.         };
  329.  
  330. struct IntuiText SCANeg =
  331.         {
  332.         0,1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL
  333.         };
  334.  
  335. /*  Special cases (display copy count) */
  336.  
  337. /***** BBANDIT Requester IntuiText's ******/
  338. struct IntuiText BBDiskbody2 =
  339.         {
  340.         0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
  341.         };
  342.  
  343. struct IntuiText BBDiskbody =
  344.         {
  345.         0,1, JAM2, 20,18, &TxtAt_Plain, ITBodyText, &BBDiskbody2
  346.         };
  347.  
  348. /***** Revenge on Disk Requester IntuiText's ******/
  349. struct IntuiText RevDiskbody3 =
  350.         {
  351.         0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
  352.         };
  353.  
  354. struct IntuiText RevDiskbody =
  355.         {
  356.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3
  357.         };
  358.  
  359.  
  360. /***** Generic Notice - Removed from Memory ****/
  361. struct IntuiText GRB3 =
  362.         {
  363.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled.  See the", NULL
  364.         };
  365.  
  366. struct IntuiText GRB2 =
  367.         {
  368.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &GRB3
  369.         };
  370.  
  371. struct IntuiText GenericRAMBody =
  372.         {
  373.         0,1, JAM2, 20, 8, &TxtAt_Plain, ITBodyText, &GRB2
  374.         };
  375.  
  376. struct IntuiText BBMPos =
  377.         {
  378.         0,1, JAM2,  7, 3, &TxtAt_Plain, " Thanks! ", NULL
  379.         };
  380.  
  381. struct IntuiText Mem3 =
  382.         {
  383.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "some other utility is the cause of it.", NULL
  384.         };
  385.  
  386. struct IntuiText Mem2 =
  387.         {
  388.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "This could mean a new Virus is in RAM, or", &Mem3
  389.         };
  390.  
  391. struct IntuiText Mem1 =
  392.         {
  393.         0,1, JAM2, 20, 8, &TxtAt_Plain, 0 , &Mem2
  394.         };
  395.  
  396.  
  397. /***** Write Protect Error Requester IntuiText's ******/
  398. struct IntuiText ERRBody2 =
  399.         {
  400.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL
  401.         };
  402.  
  403. struct IntuiText ERRBody =
  404.         {
  405.         0,1, JAM2, 20,8, &TxtAt_Plain, (UBYTE *)"DISK ERROR:  Disk is", &ERRBody2
  406.         };
  407.  
  408. struct IntuiText ERRPos =
  409.         {
  410.         0,1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL
  411.         };
  412.  
  413. struct IntuiText ERRNeg =
  414.         {
  415.         0,1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL
  416.         };
  417.  
  418.  
  419. /***** Rewrite block?  Really? ******/
  420. struct IntuiText REWBody3 =
  421.         {
  422.         0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL
  423.         };
  424.  
  425. struct IntuiText REWBody2 =
  426.         {
  427.         0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3
  428.         };
  429.  
  430. struct IntuiText REWBody =
  431.         {
  432.         0,1, JAM2, 20,8, &TxtAt_Plain,      (UBYTE *)"Are you sure you want to", &REWBody2
  433.         };
  434.  
  435. struct IntuiText REWPos =
  436.         {
  437.         0,1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL
  438.         };
  439.  
  440. struct IntuiText REWNeg =
  441.         {
  442.         0,1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL
  443.         };
  444.  
  445.  
  446. /*********************Da Beginnin*************************/
  447.  
  448. void main(argc, argv)
  449. int argc;
  450. char **argv;
  451. {
  452.  
  453. FromCLI = TRUE;
  454.  
  455. switch (argc)
  456.         {
  457.         case 0:
  458.                 FromCLI = FALSE;
  459.                 break;
  460.  
  461.         case 3:
  462.                 NewWindow.LeftEdge = atoi(argv[1]);
  463.                 NewWindow.TopEdge = atoi(argv[2]);
  464.                 break;
  465.         };
  466.  
  467. WindowBig = FALSE;
  468.  
  469. /* Come on, folks, is intuition ever NOT going to be available???? */
  470. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  471.  
  472. /* Same with GfxBase.  If GfxBase is gone, we DESERVE to crash. */
  473. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
  474.  
  475. ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0);
  476.  
  477. diskbuffer = AllocMem((long)3*512, (long)MEMF_CHIP|MEMF_CLEAR);
  478. if (diskbuffer == 0)
  479.         {
  480.         exit(10);
  481.         };
  482.  
  483. /*  We use the same port/request through the whole program.  Works OK. */
  484. diskport = CreatePort(0L,0L);
  485. diskreq = CreateStdIO(diskport);
  486.  
  487. Window = OpenWindow(&NewWindow);
  488. if (Window == NULL)
  489.         goto Quitter;   /* No memory to open little window! */
  490.  
  491. Process = (struct Process *)FindTask(0L);
  492. Process->pr_ConsoleTask = 0;
  493.  
  494. RP = Window->RPort;
  495.  
  496. /* This does some setup stuff, I guess, eh? */
  497. SetUp();
  498.  
  499. /*  Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM.  */
  500. CheckMemoryForViruses();
  501.  
  502. CheckMemoryForIRQVirus();
  503.  
  504. CheckBlock();
  505.  
  506. DoLittle();     /* The main loop.  Do Little.  Ya. */
  507.  
  508. Quitter:
  509. if (diskport != 0) DeletePort(diskport);
  510. if (diskreq != 0) DeleteStdIO(diskreq);
  511.  
  512. CloseLibrary(GfxBase);
  513. CloseLibrary(IntuitionBase);
  514. CloseLibrary((struct Library *)ExecBase);
  515. FreeMem(diskbuffer, (long)3*512);
  516. exit(0);
  517. }
  518.  
  519. /*********************/
  520. DoLittle()
  521. {
  522. register long Code;     /* for storing our IntuiMessage stuff */
  523. register long Class;
  524. register char KG2;      /* KeepGoing 2.  Another booleean. */
  525.  
  526. KG2 = TRUE;
  527.  
  528. SetAPen(RP, 1L);
  529. SetBPen(RP, 0L);
  530. SetDrMd(RP, (long)JAM2);
  531.  
  532. while (KG2 == TRUE)
  533.         {
  534.         Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  535.         if (Message == 0)
  536.                 {
  537.                 CheckMemoryForIRQVirus();
  538.                 Delay(60);
  539.                 continue;
  540.                 };
  541.  
  542.         Class = Message->Class;
  543.         Code = Message->Code;
  544.         ReplyMsg((struct Message *)Message);
  545.  
  546.         if (Class == CLOSEWINDOW)
  547.                 {
  548.                 KG2 = FALSE;
  549.                 continue;
  550.                 };
  551.  
  552.         if (Class == MOUSEBUTTONS)
  553.                 if (Code == MENUDOWN)
  554.                         {
  555.                         Class = VANILLAKEY;
  556.                         Code = 'i';
  557.                         }
  558.                         else continue;
  559.  
  560.         if (Class == VANILLAKEY)
  561.                 {
  562.                 char flag;
  563.  
  564.                 switch (Code)
  565.                         {
  566.                         case 'i':
  567.                         case 'I':
  568.                                 if (WindowBig == TRUE) WindowBig = FALSE;
  569.                                         else WindowBig = TRUE;
  570.  
  571.                                 if (WindowBig == TRUE)
  572.                                         {
  573.                                         if (Window->TopEdge > (180-WIN_SIZE)) MoveWindow(Window, 0L, (long)-Window->TopEdge);
  574.                                         SizeWindow(Window, 0L, WIN_SIZE);
  575.                                         } else SizeWindow(Window, 0L, -WIN_SIZE);
  576.  
  577.                                 WaitForNewSize();
  578.                                 break;
  579.  
  580.  
  581.                         case 'c':
  582.                         case 'C':
  583.                                 for (x=0; x<4; x++) ChangeCount[x] = 10000;
  584.                                 CheckBlock();
  585.  
  586.                         default:
  587.                                 flag = ShowAscii(Code);
  588.                                 if (flag == 1) CheckBlock();
  589.                         };
  590.                 if (WindowBig == TRUE) DoStats();
  591.                 };
  592.  
  593.         if (Class == DISKINSERTED)
  594.                 {
  595.                 CheckBlock();
  596.                 if (WindowBig == TRUE) DoStats();
  597.                 };
  598.         };
  599.  
  600. CloseWindow(Window);
  601. }
  602.  
  603.  
  604. /************************************************/
  605. /* Opens trackdisk, finds out who's out there,  */
  606. /* and sets Changecount up accordioningly.      */
  607. /************************************************/
  608. SetUp()
  609. {
  610. long x;
  611.  
  612. for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
  613.         {
  614.         ChangeCount[x] = 1000;
  615.         error = OpenDevice(TDName,(long)x,diskreq,0L);
  616.         if (error > 0)
  617.                 {
  618.                 ChangeCount[x] = -1;
  619.                 } else CloseDevice(diskreq);
  620.         };
  621.  
  622. }
  623.  
  624. /*********************************************************/
  625. /* This routine returns which drive changed disks lately */
  626. /*********************************************************/
  627. WhoChanged()
  628. {
  629. char RetVal = -1;       /* The value we'll return */
  630.  
  631. for (x = 0; x < 4; x++)
  632.         {
  633.         if (ChangeCount[x] == -1)
  634.                 continue;       /* no drive here */
  635.         error = OpenDevice(TDName,(long)x,diskreq,(long)0);
  636.         if (error > 0)
  637.                 continue;       /* no drive here */
  638.  
  639.         diskreq->io_Command = TD_CHANGESTATE;
  640.         DoIO(diskreq);
  641.         if (diskreq->io_Actual != 0)
  642.                 {
  643.                 CloseDevice(diskreq);
  644.                 continue;
  645.                 };
  646.  
  647.         diskreq->io_Command = TD_CHANGENUM;
  648.         DoIO(diskreq);
  649.         if (diskreq->io_Actual != ChangeCount[x])
  650.                 {
  651.                 RetVal = x;
  652.                 ChangeCount[x] = diskreq->io_Actual;
  653.                 CloseDevice(diskreq);
  654.                 break;
  655.                 };
  656.  
  657.         CloseDevice(diskreq);
  658.         };
  659.  
  660. return(RetVal);
  661. }
  662.  
  663. /****************************************************************/
  664. /*  Figures out which drive changed disks (using WhoChanged(),  */
  665. /*  And checks it.  Calling this after every DISKINSERTED is OK.*/
  666. /****************************************************************/
  667. CheckBlock()
  668. {
  669. /*  How many register vars can I use, anyway? */
  670. register long Sum, Virus;
  671. register long a, Unit;
  672. char SCA, ByteWarrior, Revenge, BBandit;
  673. char NorthStar, Obelisk, Pentagon, SystemZ;
  674. register unsigned long *iptr;
  675. unsigned long *ptr;
  676. char drivename[10];
  677.  
  678. while ((Unit = WhoChanged()) != -1)
  679.         {
  680.         sprintf(drivename, "DF%c:", Unit+'0');
  681.  
  682.         SCA = FALSE;
  683.         BBandit = FALSE;
  684.         Revenge = FALSE;
  685.         ByteWarrior = FALSE;
  686.         NorthStar = FALSE;
  687.         Obelisk = FALSE;
  688.     Pentagon = FALSE;
  689.     SystemZ = FALSE;
  690.     
  691.         /* Unit # to open is returned by "WhoChanged()" up above. */
  692.         if (Unit == -1) return;
  693.         error = OpenDevice(TDName,(long)Unit,diskreq,0L);
  694.         if (error > 0) return;
  695.  
  696.         DisksChecked++;
  697.  
  698.         error = ReadBlock();
  699.         CloseDevice(diskreq);
  700.         if (error == FALSE) return;
  701.  
  702.         ptr = (long *)diskbuffer;
  703.         iptr = (long *)diskbuffer;
  704.  
  705.         if (iptr[0] != ID_DOS_DISK) return;     /* No DOS/0 */
  706.  
  707.         Sum = 0;
  708.         for (a=0; a<256 /*1024/4 cuz we're dealing with ptr math now*/  ; a++)
  709.                 {
  710.                 LastSum = Sum;
  711.                 Sum = Sum + ptr[a];
  712.                 if (LastSum > Sum) Sum++;  /* took me a while to figger this out */
  713.                 }
  714.  
  715.         if (Sum != 0)
  716.                 {
  717.                 CheckDriveForIRQ(drivename);
  718.                 return; /* if it's not bootable, we DONT want it! */
  719.                 };
  720.  
  721.  
  722.     if (diskbuffer[0x40] == 0xff)
  723.         if (diskbuffer[0x41] == 0xa0)
  724.             if (diskbuffer[0x42] == 0x20)
  725.                 if (diskbuffer[0x42] == 0x40)
  726.                     {
  727.                     PentagonCount++;
  728.                     Pentagon = TRUE;
  729.                     }
  730.                     
  731.     if (diskbuffer[0x170] == 0xfe)
  732.         if (diskbuffer[0x171] == 0x3a)
  733.             if (diskbuffer[0x172] == 0x4c)
  734.                 if (diskbuffer[0x173] == 0xdf)
  735.                     {
  736.                     SystemZCount++;
  737.                     SystemZ = TRUE;
  738.                     }
  739.                     
  740.        if (diskbuffer[0x34] == 100)
  741.                 if (diskbuffer[0xc4] == 48)
  742.                         if (diskbuffer[0xc0] == 68)
  743.                                 if (diskbuffer[0xf1] == 7)
  744.                                         {
  745.                                         ByteWarriorCount++;
  746.                                         ByteWarrior = TRUE;
  747.                                         };
  748.  
  749.         if (diskbuffer[0x2b] == '9')
  750.                 if (diskbuffer[0x2c] == '.')
  751.                         if (diskbuffer[0x2d] == '8')
  752.                                 if (diskbuffer[0x2e] == '7')
  753.                                         {
  754.                                         ByteBanditCount++;
  755.                                         BBandit = TRUE; /* 9.87 is part of BBandit Virus */
  756.                                         };
  757.  
  758.         /* check specifically for SCA virus */
  759.         if (diskbuffer[8] == 'C')
  760.                 if (diskbuffer[9] == 'H')
  761.                         if (diskbuffer[10] == 'W')
  762.                                         {
  763.                                         SCA = TRUE;     /* CHW is part of SCA virus */
  764.                                         SCACount++;
  765.                                         };
  766.  
  767.         if (diskbuffer[0xe] == 'I')
  768.                 if (diskbuffer[0xf] == 'D')
  769.                         if (diskbuffer[0x10] == '9')
  770.                                 if (diskbuffer[0x1a6] == 'f')
  771.                                         {
  772.                                         Revenge= TRUE;
  773.                                         RevengeCount++;
  774.                                         };
  775.  
  776.         if (diskbuffer[0x12] == 78)
  777.                 if (diskbuffer[0x13c] == 68)
  778.                         if (diskbuffer[0x18] == 83)
  779.                                 if (diskbuffer[0x19] == 116)
  780.                                         {
  781.                                         NorthStar = TRUE;
  782.                                         NorthStarCount++;
  783.                                         };
  784.  
  785.  
  786.         if (diskbuffer[0x38] == 71)
  787.                 if (diskbuffer[0xbc] == 83)
  788.                         if (diskbuffer[0x1fb] == 100)
  789.                                 if (diskbuffer[0x2d] == 80)
  790.                                         {
  791.                                         Obelisk = TRUE;
  792.                                         ObeliskCount++;
  793.                                         };
  794.  
  795.         /* compare boot block with real boot block.  If it's not, notify God. */
  796.         Virus = FALSE;
  797.  
  798.         for (x = 0; x < 39; x++) /* num of bytes in bootblock */
  799.                 {
  800.                 if (diskbuffer[8+x] != bootblock[8+x])
  801.                         {
  802.                         Virus = TRUE;
  803.                         };
  804.                 };
  805.  
  806.         /* Oh no, a Virus! */
  807.         if (Virus == TRUE)
  808.                 {
  809.                 NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
  810.                 TEXTPTR[23] = '0'+Unit;
  811.                 error = FALSE;
  812.  
  813.                 if (SCA == TRUE)
  814.                         {
  815.                         /* OH NOOOOO, an SCA virus.  Wimpo virus, compared to BBandit
  816.                            but it's a lot nicer code to read. */
  817.                         error = MyRequest(VN_SCA, 1);
  818.                         }
  819.                 else if (BBandit == TRUE)
  820.                         {
  821.                         /* The Byte Bandit Virus.  Tricky bugger, he WAS. Cheats, tho. */
  822.                         sprintf(CopyText, copystring, (diskbuffer[74]*256)+diskbuffer[75]);
  823.                         BuildITBodyText(VN_BYTEBANDIT, 1);
  824.                         error = AutoRequest(Window, &BBDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
  825.                         }
  826.                 else if (Revenge == TRUE)
  827.                         {
  828.                         /* Revenge virus.  X rated bugger, lot like Byte Bandit. */
  829.                         sprintf(CopyText, copystring, (diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
  830.                         BuildITBodyText(VN_REVENGE, 1);
  831.                         error = AutoRequest(Window, &RevDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
  832.                         }
  833.                 else if (ByteWarrior == TRUE)
  834.                         {
  835.                         /* Byte Warrior.  Very 'friendly' virus.  Ez to get rid of.  */
  836.                         error = MyRequest(VN_BYTEWARRIOR, 1);
  837.                         }
  838.                 else if (Pentagon == TRUE)
  839.                         {
  840.                         /* Pentagon Circle.  An 'AntiVirus', and not a bad one at that. */
  841.                         error = MyRequest(VN_PENTAGON, 1);
  842.                         }
  843.                 else if (SystemZ == TRUE)
  844.                         {
  845.                         /* SystemZ, Very benign, but it can spread */
  846.                         error = MyRequest(VN_SYSTEMZ, 1);
  847.                         }
  848.                 else if (NorthStar == TRUE)
  849.                         {
  850.                         /* NorthStar.  Nice virus - alerts you to others, ez to get rid of */
  851.                         error = MyRequest(VN_NORTHSTAR, 1);
  852.                         }
  853.                 else if (Obelisk == TRUE)
  854.                         {
  855.                         /* At least these guys are getting creative with their Graphics! */
  856.                         error = MyRequest(VN_OBELISK, 1);
  857.                         }
  858.                 else
  859.                         {
  860.                         /* Probably just a custom boot block (or a new virus...) */
  861.                         error = AutoRequest(Window, &Body1, &SCAPos, &SCANeg, 0L, 0L, 320L, 70L);
  862.                         }
  863.                 if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
  864.                 };
  865.         CheckDriveForIRQ(drivename);
  866.         };  /* End of While Whochanged */
  867.  
  868. }
  869.  
  870. /********************************************/
  871. /* This is where the boot code gets changed */
  872. /********************************************/
  873. DoInstall(un)
  874. int un; /* unit to write to */
  875. {
  876. register int x;
  877.  
  878. /* Rewrite disk?  Really?  */
  879. error = AutoRequest(Window, &REWBody, &REWPos, &REWNeg, 0L, 0L, 320L, 75L);
  880. if (error != TRUE) return;      /* user changed his brain. */
  881.  
  882. DisksInstalled++;
  883.  
  884. error = OpenDevice(TDName, (long)un,diskreq,0L);
  885. if (error > 0) return;
  886.  
  887. TryGain:
  888.  
  889.         diskreq->io_Command = TD_PROTSTATUS;
  890.         DoIO(diskreq);          /* check if disk is write protected */
  891.  
  892.         if (diskreq->io_Actual != 0)
  893.                 {
  894.                 error = AutoRequest(Window, &ERRBody, &ERRPos, &ERRNeg, 0L, 0L, 280L, 75L);
  895.                 if (error == TRUE) /* error is true or false, depending on user */
  896.                         {
  897.             goto TryGain;
  898.                         };
  899.             CloseDevice(diskreq);
  900.             return; /* unrecoverable write protect error!! Panic!!!!!!! */
  901.         };
  902.  
  903. for (x = 0; x < 1024; x++)
  904.         diskbuffer[x] = 0;      /* clear diskbuffer to zero.  clean. */
  905.  
  906. CopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
  907.  
  908. /* Write it ! */
  909.  
  910.         error = 0;
  911.         diskreq->io_Length = 1024; /* here we go! */
  912.         diskreq->io_Data = (APTR)diskbuffer;
  913.         diskreq->io_Command = CMD_WRITE;
  914.         diskreq->io_Offset = 0L;
  915.         DoIO(diskreq);
  916.         error = diskreq->io_Error;
  917.  
  918. if (error < 19)
  919.         {
  920.         diskreq->io_Command = CMD_UPDATE;       /* flush buffer to disk */
  921.         DoIO(diskreq);
  922.         error = diskreq->io_Error;
  923.         };
  924.  
  925. if (error < 19)
  926.         {
  927.         diskreq->io_Length = 0;
  928.         diskreq->io_Command = ETD_MOTOR;
  929.         DoIO(diskreq);                          /* turn off motor */
  930.         error = diskreq->io_Error;
  931.         };
  932.  
  933. CloseDevice(diskreq);
  934.  
  935. if (error > 19)
  936.         {
  937.         SetWindowTitles(Window, "Error, Nothing Done.", (STRPTR)-1);
  938.         }
  939.     else
  940.         {
  941.         SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
  942.         };
  943.  
  944. Delay(150L);
  945. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  946. }
  947.  
  948.  
  949. /************************/
  950.  
  951. CheckMemoryForViruses()
  952. {
  953. long Temp;
  954. unsigned short *wordpointer;
  955. unsigned long *LongMemPointer;  /* Used for reading FROM memory */
  956. unsigned long *ptr;
  957. char linebuffer[80];
  958. char *charpointer;
  959.  
  960. /**************- Check for Byte Bandit (look at TD Vector) *************/
  961. /*  (Byte Bandit isn't at a fixed location.  Depends on your RAM.      */
  962.  
  963. /* LongMemPointer = &trackdisk.device */
  964. LongMemPointer = (long *)FindName(&ExecBase->DeviceList, TDName);
  965. Temp = (long)LongMemPointer;
  966. Temp = Temp - 0x1c;
  967. LongMemPointer = (long *)Temp;
  968. VirusBase = (*LongMemPointer) - 0x1b8;
  969. LongMemPointer = (unsigned long *)VirusBase;
  970.  
  971. if (*LongMemPointer == ID_DOS_DISK)     /* klugo */
  972.         {
  973.         /* Ok, so we don't really remove it from memory, but we DO render
  974.            it harmless. */
  975.         Disable();
  976.         charpointer = (char *)VirusBase;
  977.         charpointer[0xaa] = 0x4e;
  978.         charpointer[0xac] = 0x4e;
  979.         charpointer[0xae] = 0x4e;
  980.         charpointer[0xb0] = 0x4e;
  981.  
  982.         charpointer[0xab] = 0x71;
  983.         charpointer[0xad] = 0x71;
  984.         charpointer[0xaf] = 0x71;
  985.         charpointer[0xb1] = 0x71;
  986.  
  987.         charpointer[0x1c2] = 0x60;
  988.         charpointer[0x1c3] = 0;
  989.  
  990.         charpointer[0x2d2] = 0x60;
  991.         charpointer[0x2d3] = 0;
  992.  
  993.         charpointer[0x388] = 0x4e;
  994.         charpointer[0x389] = 0x75;
  995.  
  996.         charpointer[0x3ea] = 0;
  997.         charpointer[0x3eb] = 0;
  998.  
  999.         charpointer[0] = 0;
  1000.         Enable();
  1001.  
  1002.         MyRequest(VN_BYTEBANDIT, 2);
  1003.         };
  1004.  
  1005. /****************- Look for Revenge Virus (at $7e000) ****************/
  1006. if ((unsigned long)ExecBase->CoolCapture == (unsigned long)516192)
  1007.         {
  1008.         /* Fix the CoolCapture vector */
  1009.         ExecBase->CoolCapture = 0;
  1010.  
  1011.         Disable();
  1012.  
  1013.         wordpointer = (unsigned short *)(0x7e000);
  1014.         wordpointer[0] = 0;
  1015.  
  1016.         wordpointer = (unsigned short *)(0x7e000+0x1e0);
  1017.         wordpointer[0] = 0x4ef9;
  1018.         wordpointer[1] = 0x0007;
  1019.         wordpointer[2] = 0xe066;
  1020.  
  1021.         wordpointer = (unsigned short *)0x7e2da;
  1022.         wordpointer[0] = 0x4ef9;
  1023.         wordpointer[1] = 0x0007;
  1024.         wordpointer[2] = 0xe06c;
  1025.  
  1026.         Enable();
  1027.  
  1028.         MyRequest(VN_REVENGE, 2);
  1029.         };
  1030.  
  1031. /******************** See if SCA is in RAM ***************************/
  1032. if ((long)ExecBase->CoolCapture == (long)0x7ec3e)
  1033.         {
  1034.         ExecBase->CoolCapture = 0;
  1035.         MyRequest(VN_SCA, 2);
  1036.         };
  1037.  
  1038. /***************** Check for Obelisk  *******************************/
  1039. if ((APTR)ExecBase->CoolCapture == (APTR)0x7e86c)
  1040.         {
  1041.         ExecBase->CoolCapture = 0;
  1042.         ptr = (unsigned long *)0x7e88a;
  1043.         Forbid();
  1044.         ptr[0] = 10;
  1045.         Permit();
  1046.         MyRequest(VN_OBELISK, 2);
  1047.         };
  1048.  
  1049. /******************** How about North Star? **************************/
  1050. if ((APTR)ExecBase->CoolCapture == (APTR)0x7ec0e)
  1051.         {
  1052.         ExecBase->CoolCapture = 0;
  1053.         MyRequest(VN_NORTHSTAR, 2);
  1054.         };
  1055.  
  1056. /********************* Check for Byte Warrior ************************/
  1057. wordpointer = (unsigned short *)0x7f800;
  1058. if ( wordpointer[0] == (0x444f) )
  1059.         {
  1060.         wordpointer = (unsigned short *)0x7f954;
  1061.         if (wordpointer[0] == 0x4afc)
  1062.                 {
  1063.                 wordpointer[0] = 0;             /* Kill resident matchtag */
  1064.  
  1065.                 Forbid();
  1066.  
  1067.                 wordpointer = (unsigned short *)0x7f972;
  1068.                 wordpointer[0] = 0x4ef9;
  1069.                 wordpointer[1] = 0x00fc;
  1070.                 wordpointer[2] = 0x06dc;
  1071.  
  1072.                 wordpointer =  (unsigned short *)0x7f800;
  1073.                 wordpointer[0] = 0;
  1074.  
  1075.                 Permit();
  1076.  
  1077.                 MyRequest(VN_BYTEWARRIOR, 2);
  1078.                 };
  1079.         };
  1080.  
  1081. /******************** See if Pentagon is in RAM ***************************/
  1082. if ((long)ExecBase->CoolCapture == (long)0x7fb4c)
  1083.         {
  1084.         ExecBase->CoolCapture = 0;
  1085.  
  1086.         /* He sometimes has the DoIO() setfunctioned, I can't figure out
  1087.            when, but even if he does, he doesn't do any harm anyway, and
  1088.            with CoolCapture set to 0, he'll be gone at next reboot.  */
  1089.            
  1090.         MyRequest(VN_PENTAGON, 2);
  1091.     };
  1092.     
  1093. /********************* Check for Byte Warrior ************************/
  1094. wordpointer = (unsigned short *)0x7f4e0;
  1095. if ( wordpointer[0] == (0x4afc) )
  1096.         {
  1097.     if (wordpointer[1] == 0x0007)
  1098.         {
  1099.         wordpointer[0] = 0;
  1100.         
  1101.         MyRequest(VN_SYSTEMZ, 2);
  1102.         };
  1103.     }
  1104.  
  1105.  
  1106.  
  1107. if (ExecBase->CoolCapture != 0)
  1108.         {
  1109.         sprintf(linebuffer, "Cool%s%x", CaptureStr, ExecBase->CoolCapture);
  1110.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0;
  1111.         }
  1112.  
  1113. if (ExecBase->ColdCapture != 0)
  1114.         {
  1115.         sprintf(linebuffer, "Cold%s%x", CaptureStr, ExecBase->ColdCapture);
  1116.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0;
  1117.         }
  1118.  
  1119. if (ExecBase->WarmCapture != 0)
  1120.         {
  1121.         sprintf(linebuffer, "Warm%s%x", CaptureStr, ExecBase->WarmCapture);
  1122.         if (MyRequest(linebuffer, 3) == TRUE) ExecBase->WarmCapture = 0;
  1123.         }
  1124.  
  1125.  
  1126. }
  1127.  
  1128.  
  1129. /**************************************************************/
  1130. /*  This is the routine that displauys a block as ASCII text. */
  1131. /**************************************************************/
  1132. ShowAscii(key)
  1133. long key;
  1134. {
  1135. int drive;
  1136. int x,y;
  1137. int deltax, deltay;
  1138. long a;
  1139. int FLAG=0;
  1140.  
  1141. struct RastPort *RP;
  1142. RP = Window->RPort;
  1143.  
  1144. drive = key - '0';
  1145.  
  1146. if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
  1147.  
  1148. error = OpenDevice(TDName,(long)drive,diskreq,0L);
  1149. if (error > 0) return;
  1150.  
  1151. error = ReadBlock();
  1152.  
  1153. CloseDevice(diskreq);
  1154.  
  1155. if (error == FALSE) return;
  1156.  
  1157. /* save the amount we moved the window */
  1158. deltax = Window->LeftEdge;
  1159. deltay = Window->TopEdge;
  1160.  
  1161. MoveWindow(Window, -deltax, -deltay);
  1162.  
  1163. if (WindowBig == FALSE) SizeWindow(Window, 278L, 160L);
  1164.         else SizeWindow(Window, 278L, 60L);
  1165.  
  1166. WaitForNewSize();
  1167.  
  1168. SetAPen(RP, 3L);
  1169. Move(RP, (long)(14+(12*8)), 165L);
  1170. Text(RP, "Block 0", 7L);
  1171. Move(RP, (long)(324+(12*8)), 165L);
  1172. Text(RP, "Block 1", 7L);
  1173. SetAPen(RP, 1L);
  1174.  
  1175. text[2] = key;
  1176. SetWindowTitles(Window, text, (STRPTR)-1);
  1177.  
  1178. x=0; y=0;
  1179.  
  1180. SetAPen(RP, 1L);
  1181. SetDrMd(RP, JAM2);
  1182.  
  1183. for (a=0; a<512; a=a+32)
  1184.         {
  1185.         Move(RP, (long)(10+(x*8)), (long)20+(y*9));
  1186.         Text(RP, &diskbuffer[a], 32L);
  1187.  
  1188.         Move(RP, (long)(320+(x*8)), (long)20+(y*9));
  1189.         Text(RP, &diskbuffer[a+512], 32L);
  1190.         y++;
  1191.         };
  1192.  
  1193. Wait(1<<Window->UserPort->mp_SigBit);
  1194. Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1195.  
  1196. /*  If a disk was inserted, we want CheckBlock() to happen later on some time */
  1197. if (Message->Class == DISKINSERTED) FLAG=1;
  1198. ReplyMsg((struct Message *)Message);
  1199.  
  1200. if (WindowBig == FALSE)
  1201.         SizeWindow(Window, -278L, -160L);
  1202.         else SizeWindow(Window, -278L, -60L);
  1203.  
  1204. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  1205. WaitForNewSize();
  1206.  
  1207. /* deltas plus current position, in case dude moved the window */
  1208. MoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
  1209. Delay(2L);
  1210. return(FLAG);
  1211. }
  1212.  
  1213.  
  1214. /*
  1215.  When you do a SizeWindow() command, you have to wait for a NEWSIZE
  1216.  IntuiMessage before drawing in it.  That's all this routine does.
  1217.  */
  1218. WaitForNewSize()
  1219. {
  1220. while (TRUE)
  1221.         {
  1222.         WaitPort(Window->UserPort);
  1223.         Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1224.         if (Message->Class != NEWSIZE)
  1225.                 {
  1226.                 ReplyMsg((struct Message *)Message);
  1227.                 continue;
  1228.                 };
  1229.         ReplyMsg((struct Message *)Message);
  1230.         break;
  1231.         };
  1232. }
  1233.  
  1234. /*
  1235.         type:
  1236.  
  1237.                 1 == "is infected with the xxxx VIRUS!"
  1238.                 2 == "somethin about virus in ram"
  1239.                 3 == virus in cold/cool/warm capture
  1240. */
  1241.  
  1242. BuildITBodyText(text, type)
  1243. char *text;
  1244. int type;
  1245. {
  1246. switch (type)
  1247.         {
  1248.         case 1:
  1249.                 strcpy(ITBodyText, "infected with the `");
  1250.                 strcat(ITBodyText, text);
  1251.                 strcat(ITBodyText, "' VIRUS!");
  1252.                 break;
  1253.         case 2:
  1254.                 strcpy(ITBodyText, "NOTICE:  The `");
  1255.                 strcat(ITBodyText, text);
  1256.                 strcat(ITBodyText, "' VIRUS was found");
  1257.                 break;
  1258.         };
  1259. }
  1260.  
  1261. /***** an attempt to save space *********/
  1262. MyRequest(string, type)
  1263. char *string;
  1264. int type;
  1265. {
  1266. if (type != 3)
  1267.         {
  1268.         BuildITBodyText(string, type);
  1269.         } else
  1270.         {
  1271.         Mem1.IText = string;
  1272.         };
  1273.  
  1274. if (type == 1) return(AutoRequest(Window, &GenericDiskBody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L));
  1275. if (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 395L, 78L));
  1276. if (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 395L, 78L));
  1277. }
  1278.  
  1279.  
  1280. /********* DoStats() **********/
  1281. DoStats()
  1282. {
  1283. char linebuffer[80];
  1284.  
  1285. SetAPen(RP, 0L);
  1286. RectFill(RP, 2L, 11L, 303L, (WIN_SIZE + 7));
  1287. SetAPen(RP, 1L);
  1288.  
  1289. sprintf(linebuffer, "  Disks Checked: %d", DisksChecked);
  1290. Out(20, linebuffer);
  1291.  
  1292. sprintf(linebuffer, "Disks Installed: %d", DisksInstalled);
  1293. Out(29, linebuffer);
  1294.  
  1295. Out(43, "    Viruses Found:");
  1296.  
  1297. PV(52, VN_SCA, SCACount);
  1298. PV(61, VN_BYTEBANDIT, ByteBanditCount);
  1299. PV(70, VN_NORTHSTAR, NorthStarCount);
  1300. PV(79, VN_BYTEWARRIOR, ByteWarriorCount);
  1301. PV(88, VN_REVENGE, RevengeCount);
  1302. PV(97, VN_OBELISK, ObeliskCount);
  1303. PV(106, VN_IRQ, IRQFound);
  1304. PV(115, VN_PENTAGON, PentagonCount);
  1305. PV(124, VN_SYSTEMZ, SystemZCount);
  1306. }
  1307.  
  1308. /****************** Ok, we're REALLY being chintzy here. */
  1309. PV(num, name, howmany)
  1310. int num;
  1311. char *name;
  1312. int howmany;
  1313. {
  1314. char linebuffer[80];
  1315.  
  1316. sprintf(linebuffer, "%-16s: %d", name, howmany);
  1317. Out(num, linebuffer);
  1318. }
  1319.  
  1320. /***************************************** Cheap?  Me?  Nooooo....     */
  1321. /* This will write text to the column number in NUM, the text in Name. */
  1322. /*  Or something like that. ********************************************/
  1323. Out(num, name)
  1324. int num;
  1325. char *name;
  1326. {
  1327. int len;
  1328. len = 0;
  1329.  
  1330. while (name[len] != 0) len++;
  1331.  
  1332. Move(RP, 20L, (long)num);
  1333. Text(RP, name, len);
  1334. }
  1335.  
  1336.  
  1337. ReadBlock()
  1338. {
  1339. diskreq->io_Command = CMD_READ;
  1340. diskreq->io_Data = (APTR)diskbuffer;
  1341. diskreq->io_Length = 3*512;
  1342. diskreq->io_Offset = 0;
  1343. DoIO(diskreq);
  1344. if (diskreq->io_Error > 0) return(FALSE);
  1345. diskreq->io_Length = 0;
  1346. diskreq->io_Command = TD_MOTOR;
  1347. DoIO(diskreq);
  1348. return(TRUE);
  1349. }
  1350.  
  1351. unsigned long *OpenLibVectorPtr;
  1352. unsigned long *EntryForOldOpenLib;
  1353. unsigned long *OldOldOpenLibVector;
  1354.  
  1355.  
  1356. CheckMemoryForIRQVirus()
  1357. {
  1358. long *Array;
  1359. int Num;
  1360.  
  1361. Array = (long *)4;
  1362. Array = (long *)Array[0];
  1363. Num = (int)Array;
  1364. Num = Num - 0x196;
  1365.  
  1366. OpenLibVectorPtr = (unsigned long *)Num;
  1367.  
  1368. EntryForOldOpenLib = (unsigned long *)OpenLibVectorPtr[0];
  1369. OldOldOpenLibVector = (unsigned long *)(((char *)EntryForOldOpenLib) + 0x12);
  1370.  
  1371. if (EntryForOldOpenLib[0] == 0x2f3a0010)
  1372.         {
  1373.  
  1374. /*
  1375.         printf("Setting $%x to $%x\n", OpenLibVectorPtr, OldOldOpenLibVector[0]);
  1376. */
  1377.  
  1378.         OpenLibVectorPtr[0] = OldOldOpenLibVector[0];
  1379.         ExecBase->KickTagPtr = 0;
  1380.         MyRequest(VN_IRQ, 2);
  1381.         };
  1382. }
  1383.  
  1384.  
  1385. /********************************/
  1386.  
  1387. CheckDriveForIRQ(drivename)
  1388. char *drivename;
  1389. {
  1390. int err;
  1391. char buffer[80];
  1392. char dirbuffer[80];
  1393. char filebuffer[100];
  1394. char tempbuffer[100];
  1395. char FoundInDir;
  1396. char FoundInFname;
  1397. char chr;
  1398. int index;
  1399. char pass;
  1400.  
  1401. FoundInDir = FALSE;
  1402. FoundInFname = FALSE;
  1403. filebuffer[0] = 0;
  1404.  
  1405. pass = 0;
  1406.  
  1407. sprintf(dirbuffer, "%sC/DIR", drivename);
  1408. err = CheckFileForIRQ(dirbuffer,0);
  1409. if (err == 1)
  1410.         {
  1411.         IRQFound++;
  1412.         FoundInDir = TRUE;
  1413.         }
  1414.         else dirbuffer[0] = 0;
  1415.  
  1416.  
  1417. index = 0;
  1418.  
  1419. sprintf(tempbuffer, "%ss/Startup-Sequence", drivename);
  1420. fp = Open(tempbuffer, MODE_OLDFILE);
  1421. if (fp == 0)
  1422.         filebuffer[0] = 0;
  1423.         else
  1424.         {
  1425.         while (TRUE)
  1426.                 {
  1427.                 err = Read(fp, &chr, 1);
  1428.                 if (err == 0) break;
  1429.                 if (chr == 34) continue;
  1430.                 if (chr == 0x0a) continue;
  1431.                 if (chr == ';') continue;
  1432.                 if (chr == ' ') continue;
  1433.                 break;
  1434.                 };
  1435.  
  1436.         if (err != 0)
  1437.                 {
  1438.                 while (TRUE)
  1439.                         {
  1440.                         filebuffer[index++] = chr;
  1441.                         filebuffer[index] = 0;
  1442.                         err = Read(fp, &chr, 1);
  1443.                         if (err == 0) break;
  1444.                         if (chr == 34) break;
  1445.                         if (chr == 0x0a) break;
  1446.                         if (chr == ';') break;
  1447.                         if (chr == 32) break;
  1448.                         };
  1449.                 };
  1450.  
  1451.         Close(fp);
  1452.  
  1453.         sprintf(buffer, "%s%s", drivename, filebuffer);
  1454.  
  1455.         err = CheckFileForIRQ(buffer, 0);
  1456.         if (err == -1)
  1457.                 {
  1458.                 sprintf(buffer, "C:%s", filebuffer);
  1459.                 err = CheckFileForIRQ(buffer, 0);
  1460.                 };
  1461.  
  1462.         strcpy(filebuffer, buffer);
  1463.  
  1464.         if (err == 1)
  1465.                 {
  1466.                 FoundInFname = TRUE;
  1467.                 IRQFound++;
  1468.                 }
  1469.                 else filebuffer[0] = 0;
  1470.         };
  1471.  
  1472. if (FoundInDir == FALSE && FoundInFname == FALSE) return(0);
  1473.  
  1474. WBenchToFront();
  1475. fp = Open("CON:70/20/500/100/VirusX", MODE_NEWFILE);
  1476. if (fp == 0) return(0);
  1477.  
  1478. WriteFP(fp, "NOTICE:  The IRQ Virus was found on volume ");
  1479. WriteFP(fp, drivename);
  1480. WriteFP(fp, "\n");
  1481.  
  1482. while (TRUE)
  1483.         {
  1484.         if (pass == 0)
  1485.                 {
  1486.                 strcpy(tempbuffer, dirbuffer);
  1487.                 }
  1488.         else if (pass == 1)
  1489.                 {
  1490.                 strcpy(tempbuffer, filebuffer);
  1491.                 }
  1492.         else if (pass == 2) break;
  1493.  
  1494.         pass++;
  1495.  
  1496.         if (tempbuffer[0] == 0) continue;
  1497.  
  1498.         sprintf(buffer, "\nIn the command: %s\n", tempbuffer);
  1499.         WriteFP(fp, buffer);
  1500.         WriteFP(fp, "Okay to remove it? [Y]: ");
  1501.         Read(fp, buffer, 3);
  1502.         if (toupper(buffer[0]) == 'Y')
  1503.                 {
  1504.                 err = CheckFileForIRQ(tempbuffer, 1);
  1505.                 if (err == 1)
  1506.                         {
  1507.                         WriteFP(fp, "Virus removed.\n");
  1508.                         } else
  1509.                         {
  1510.                         sprintf(buffer, "Error #%d removing virus.  Check file.\n", err);
  1511.                         WriteFP(fp, buffer);
  1512.                         }
  1513.                 };
  1514.         };
  1515.  
  1516. WriteFP(fp, "\nHit RETURN to continue...");
  1517. Read(fp, buffer, 3);
  1518. Close(fp);
  1519. }
  1520.  
  1521. WriteFP(fp, string)
  1522. int fp;
  1523. char *string;
  1524. {
  1525. Write(fp, string, strlen(string));
  1526. }
  1527.  
  1528. /********************************/
  1529.  
  1530. #define VTAG     0x00000109L
  1531. #define BEGIN    OFFSET_BEGINNING
  1532. #define END              OFFSET_END
  1533. #define OLD              MODE_OLDFILE
  1534. #define NEW              MODE_NEWFILE
  1535. #define SLONG    ((long)sizeof(long))
  1536. #define OK        1                     /* no error */
  1537.  
  1538. #define NOFILE   -1                     /* can't find file */
  1539. #define SEEKERR  -2                     /* seek error on file */
  1540. #define ALLOCERR -3                     /* can't allocate memory */
  1541. #define READERR  -4                     /* error reading file */
  1542. #define VIRUSNF  -5                     /* virus not found in file */
  1543. #define WRITERR  -6                     /* error writing to file */
  1544. #define OPENERR  -7                     /* error opening file for write */
  1545. #define NOTEXE   -8                     /* not an executable file */
  1546.  
  1547. #define GOTHIM   OK                     /* removed virus from file */
  1548.  
  1549. #define VTAG     0x00000109L            /* virus hunk length */
  1550. #define VSIG1    0x0000FFFEL            /* part of virus signature */
  1551. #define VSIG2    0x61000000L            /* part of virus signature */
  1552.  
  1553.  
  1554. static long inp, *buff, size;
  1555.  
  1556. cleanup(val)
  1557. int val;
  1558. {
  1559.         if(inp)         Close(inp);
  1560.         if(buff)        FreeMem(buff,size);
  1561.         return val;
  1562. }
  1563.  
  1564. CheckFileForIRQ(fname, flag)
  1565. char *fname;
  1566. int flag;
  1567. {
  1568.  
  1569.         int   i = 0;
  1570.         long  fhunk, lhunk, nhunk;
  1571.         long tbuff[488/4];
  1572.  
  1573.         inp = 0L;  buff = 0L;
  1574.  
  1575.         if((inp = Open(fname,OLD)) == 0)        /* open the desired file */
  1576.                 return NOFILE;
  1577.  
  1578.         Read(inp,(char *)&tbuff[0],487);                                /* get the first long word */
  1579.         if(tbuff[0] != 0x000003F3)                              /* check for executable file */
  1580.                 return cleanup(NOTEXE);
  1581.  
  1582.         if(tbuff[5] != VTAG)
  1583.                 return cleanup(VIRUSNF);
  1584.  
  1585.         Seek(inp,0L,END);                               /* seek to end of file */
  1586.         size = Seek(inp,0L,BEGIN);              /* rewind the file to get size */
  1587.         if(size <= 0L)
  1588.                 return cleanup(SEEKERR);
  1589.  
  1590.         if((buff = AllocMem(size,0L)) == 0)     /* mem buffer for file */
  1591.                 return cleanup(ALLOCERR);
  1592.  
  1593.         if(Read(inp,(char *)&buff[0],size) != size)     /* read entire file into buffer */
  1594.                 return cleanup(READERR);
  1595.  
  1596.         nhunk = buff[ 2 ];              /* number of hunks in file */
  1597.         fhunk = buff[ 3 ];              /* first hunk */
  1598.         lhunk = buff[ 4 ];              /* last hunk */
  1599.  
  1600. /*
  1601.         the IRQ virus inserts his code as the first hunk in the file
  1602.         we can find the first hunk in the 6th longword of the file
  1603. */
  1604.         /* find the start of the virus hunk */
  1605.         while(buff[ i++ ] != 0x000003E9)
  1606.                 ;
  1607. /*
  1608.         The virus checks the first hunk for it's signature to prevent
  1609.         reinfecting an already infected program.  It actually checks for
  1610.         0xFFFE6100 which is the lower half of a move.m instruction and
  1611.         the upper half of a bsr instruction.  Here we do the same.
  1612.     i points to the virus code hunk length.
  1613. */
  1614.         if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
  1615.      || ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
  1616.                 return cleanup(VIRUSNF);
  1617.  
  1618.         if (flag == 0)
  1619.                 return cleanup(1);
  1620.  
  1621. /*
  1622.         close the file and reopen it with write access
  1623.         mode NEW will effectivly delete the old file contents so if a
  1624.         file error occurs before we finish, the file will be corrupt
  1625. */
  1626.         Close(inp);
  1627.         if((inp = Open(fname,NEW)) == 0)
  1628.                 return cleanup(OPENERR);
  1629.  
  1630.         buff[2] -= 1;   buff[4] -= 1;   /* readjust program header info */
  1631.  
  1632. /* write new header */
  1633.         if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
  1634.                 return cleanup(WRITERR);
  1635.  
  1636.         if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
  1637.                 return cleanup(WRITERR);
  1638.  
  1639. /*
  1640.         subtract length of virus hunk and overhead from file size
  1641.         i was calculated earlier
  1642. */
  1643.         i = i + 8L + VTAG;
  1644.         size = (size/SLONG - i)*SLONG;
  1645.  
  1646. /* and write old code out to file, ignoring virus hunk */
  1647.         if(Write(inp,(char *)&buff[i],size) != size)
  1648.                 return cleanup(WRITERR);
  1649.  
  1650. /* we're done, the file is clean and intact */
  1651.         return cleanup(GOTHIM);
  1652. }
  1653.